package wortubung.lang.de;

import static wortubung.lang.LanguageManager.DE_PREFIXES_FILE;
import static wortubung.util.LatinScript.*;
import static wortubung.util.CommonUtils.*;

import java.io.IOException;
import java.util.ArrayList;

import wortubung.core.LANG;
import wortubung.core.POS;
import wortubung.inflection.PrefixMatcher;
import wortubung.util.ImmutableStringList;
import wortubung.util.TransliterateException;

public class DeutschSpracheWerkzeug {

	public static final String ___ = "_";

	public static final String[] MFNP_NAMES = { "Single-m.", "Single-f.", "Single-nt.", "Plural" };
	public static final String[] MFN_NAMES  = { "Single-m.", "Single-f.", "Single-nt." };
	public static final String[] SP_NAMES   = { "Single", "Plural" };
	public static final String[] SorP_NAMES = { "Single/Plural" };
	public static final String[] S_NAMES    = { "Single" };
	public static final String[] P_NAMES    = { "Plural" };

	public static final String ADJ_DER_USAGE    = "adj.-der";
	public static final String ADJ_EIN_USAGE    = "adj.-ein";
	public static final String ADJ_STRONG_USAGE = "adj.-strong";

	public static final PrefixMatcher verbPrefixMatcher;

	static {
		ArrayList<String> verbPrefices = new ArrayList<String>();
		ArrayList<String> fauxPrefices = new ArrayList<String>();
		try {
			String[] lines = readFileFromCPAsString(DE_PREFIXES_FILE).split("\n");
			for (String line : lines) {
				line = line.trim();
				if (isEmpty(line) || line.startsWith("#"))
					continue;
				int idx = line.indexOf(" ");
				if (idx > 0)
					line = line.substring(0, idx);
				if (line.startsWith("!"))
					fauxPrefices.add(LANG.de.toVernacular(line.substring(1)));
				else
					verbPrefices.add(LANG.de.toVernacular(line));
			}
		} catch (IOException e) {
			e.printStackTrace();
		} catch (TransliterateException e) {
			e.printStackTrace();
		}
		verbPrefixMatcher = new PrefixMatcher(LANG.de, verbPrefices, fauxPrefices);
	}

	public static String getVerbStem(String verb) {
		return chopRight(verb, verb.endsWith("en") ? 2 : 1);
	}

	public static boolean isDefault(String rule) {
		return ___.equals(rule);
	}

	public static boolean hasDefault(String... rules) {
		for (String rule : rules)
			if (isDefault(rule))
				return true;
		return false;
	}

	public static String addFirstUmlaut(String root) {
		for (int i=0; i<root.length(); ++i) {
			char umlaut = ' ';
			switch (root.charAt(i)) {
			case 'a': umlaut = 'ä'; break;
			case 'o': umlaut = 'ö'; break;
			case 'u': umlaut = 'ü'; break;
			}
			if (umlaut != ' ')
				return root.substring(0, i) + umlaut + root.substring(i+1);
		}
		return root;
	}

	public static String singleSyllableAddUmlaut(String word) {
		char vowel = ' ';
		int  vowelIndex = -1;
		for (int i=0; i<word.length(); ++i) {
			char ch = word.charAt(i);
			switch(ch) {
			case 'a':
				if (vowel != ' ') return word;
				vowel = 'ä';
				vowelIndex = i;
				break;
			case 'o':
				if (vowel != ' ') return word;
				vowel = 'ö';
				vowelIndex = i;
				break;
			case 'u':
				if (vowel != ' ') return word;
				vowel = 'ü';
				vowelIndex = i;
				break;
			case 'i':
			case 'e':
				if (vowel != ' ') return word;
				break;
			}
		}
		if (vowelIndex < 0)
			return word;

		String ret = "";
		if (vowelIndex > 0)
			ret += word.substring(0, vowelIndex);
		ret += vowel;
		if (vowelIndex < word.length())
			ret += word.substring(vowelIndex+1);
		return ret;
	}

	public static String appendEN(String word) {
		String ending = "en";
		if (word.endsWith("n")) {
			ending = "nen";
		} else {
			final String[] suffices = { "e", "er" };
			for (String s : suffices) {
				if (word.endsWith(s)) {
					ending = "n";
					break;
				}
			}
		}
		return word + ending;
	}

	public static String appendMissingLastN(String word) {
		return word.endsWith("n") ? word : (word + 'n');
	}

	public static String appendWithExtraE(String root, String index, POS pos) {
		return needExtraE(root, pos) ? (root + 'e' + index) : (root + index);
	}

	public static String[] appendWithExtraE(String root, ImmutableStringList indices, POS pos) {
		boolean needE = needExtraE(root, pos);

		String[] sa = new String[indices.size()];
		for (int i=0; i<sa.length; ++i) {
			String index = indices.get(i);
			if (needE && isNotEmpty(index) && !index.startsWith("e"))
				index = "e" + index;
			else if (root.endsWith("e") && index.startsWith("e"))
				index = index.substring(1);
			else if (root.endsWith("s") && index.startsWith("s"))
				index = "e" + index;
			sa[i] = root + index;
		}
		return sa;
	}

	public static String appendSansDupE(String root, String suffix) {
		if (root.endsWith("e") && suffix.startsWith("e"))
			return (suffix.length() == 1) ? root : (root + suffix.substring(1));
		return root + suffix;
	}

	public static String[] appendSansDupE(String root, String[] suffixSet, boolean[] includes) {
		int len = length(suffixSet);
		if (len == 0)
			return null;
		if (includes != null && includes.length == len) {
			for (boolean b : includes)
				if (!b)
					--len;
		}

		String[] ret = new String[len];
		int idx = 0;
		boolean rootE = root.endsWith("e");
		for (int i=0; i<suffixSet.length; ++i) {
			if (includes != null && !at(includes, i))
				continue;
			String s = neverNull(suffixSet[i]);
			if (s.startsWith("-"))
				s = s.substring(1);
			if (rootE && s.startsWith("e"))
				ret[idx] = (s.length() == 1) ? root : (root + s.substring(1));
			else
				ret[idx] = root + s;
			++idx;
		}
		trim(ret);
		return ret;
	}

	public static boolean isSingleSyllable(String word) {
		boolean hasSyllable = false;
		boolean lastVowel = false;  // for diphthong
		for (int i=0; i<word.length(); ++i) {
			if (isVowel(word.charAt(i))) {
				if (hasSyllable && !lastVowel)
					return false;
				hasSyllable = lastVowel = true;
			} else {
				lastVowel = false;
			}
		}
		return true;
	}

	public static boolean needExtraE(String root, POS pos) {
		final String[] FOR_VERBS   = { "t", "d", "fn", "chn" };
		final String[] FOR_ADJADVS = { "t", "d", "s", "z", "x", "sch" };
		if (pos.isVerb())
			return endsWith(root, FOR_VERBS);
		if (pos == POS.ADJ || pos == POS.ADV)
			return endsWith(root, FOR_ADJADVS);
		return false;
	}
}
